package com.huanzhidadi.rollback.handler;

import com.huanzhidadi.rollback.exception.BaseException;
import com.huanzhidadi.rollback.model.BaseResultVO;
import lombok.extern.slf4j.Slf4j;
import org.springframework.beans.ConversionNotSupportedException;
import org.springframework.beans.TypeMismatchException;
import org.springframework.http.converter.HttpMessageNotReadableException;
import org.springframework.http.converter.HttpMessageNotWritableException;
import org.springframework.jdbc.BadSqlGrammarException;
import org.springframework.validation.BindException;
import org.springframework.validation.ObjectError;
import org.springframework.web.HttpMediaTypeNotAcceptableException;
import org.springframework.web.HttpRequestMethodNotSupportedException;
import org.springframework.web.bind.MethodArgumentNotValidException;
import org.springframework.web.bind.MissingServletRequestParameterException;
import org.springframework.web.bind.annotation.ControllerAdvice;
import org.springframework.web.bind.annotation.ExceptionHandler;
import org.springframework.web.bind.annotation.ResponseBody;

import java.io.IOException;
import java.util.List;
import java.util.Objects;

/**
 * 自定义异常(MyCustomExceptionHandler)
 */
@Slf4j
@ResponseBody
@ControllerAdvice
public class MyCustomExceptionHandler {

    //空指针异常
    @ExceptionHandler(NullPointerException.class)
    public BaseResultVO nullPointerExceptionHandler(NullPointerException exception) {
        log.error("1001..NullPointerException", exception);
        return BaseResultVO.error(1001, exception.getMessage());
    }
    //类型转换异常
    @ExceptionHandler(ClassCastException.class)
    public BaseResultVO classCastExceptionHandler(ClassCastException exception) {
        log.error("1002..ClassCastException", exception);
        return BaseResultVO.error(1002, exception.getMessage());
    }

    //IO异常
    @ExceptionHandler(IOException.class)
    public BaseResultVO iOExceptionHandler(IOException exception) {
        log.error("1003..IOException", exception);
        return BaseResultVO.error(1003, exception.getMessage());
    }
    //未知方法异常
    @ExceptionHandler(NoSuchMethodException.class)
    public BaseResultVO noSuchMethodExceptionHandler(NoSuchMethodException exception) {
        log.error("1004..NoSuchMethodException", exception);
        return BaseResultVO.error(1004, exception.getMessage());
    }

    //数组越界异常
    @ExceptionHandler(IndexOutOfBoundsException.class)
    public BaseResultVO indexOutOfBoundsExceptionHandler(IndexOutOfBoundsException exception) {
        log.error("1005..IndexOutOfBoundsException", exception);
        return BaseResultVO.error(1005, exception.getMessage());
    }
    //算术运算异常
    @ExceptionHandler(ArithmeticException.class)
    public BaseResultVO arithmeticExceptionHandler(ArithmeticException exception) {
        log.error("1006..ArithmeticException", exception);
        return BaseResultVO.error(1006, exception.getMessage());
    }
    // Required request body is missing
    @ExceptionHandler({HttpMessageNotReadableException.class})
    public BaseResultVO requestNotReadable(HttpMessageNotReadableException exception){
        log.error("400..HttpMessageNotReadableException", exception);
        return BaseResultVO.error(400, exception.getMessage());
    }
    //400错误
    @ExceptionHandler({TypeMismatchException.class})
    public BaseResultVO requestTypeMismatch(TypeMismatchException exception){
        log.error("400..TypeMismatchException", exception);
        return BaseResultVO.error(400, exception.getMessage());
    }

    //400错误
    @ExceptionHandler({MissingServletRequestParameterException.class})
    public BaseResultVO requestMissingServletRequest(MissingServletRequestParameterException exception){
        log.error("400..MissingServletRequestParameterException", exception);
        return BaseResultVO.error(400, exception.getMessage());
    }
    //参数校验错误
    @ExceptionHandler({MethodArgumentNotValidException.class, BindException.class})
    public BaseResultVO methodArgumentNotValidExceptionHandler(BindException exception){
        log.error("400..MethodArgumentNotValidException", exception);
        StringBuffer sb = null;
        List<ObjectError> allErrors = exception.getBindingResult().getAllErrors();
        for (ObjectError error : allErrors) {
            // log.error("-------参数校验异常-------->:{}", error);
            if (Objects.isNull(sb)) {
                sb = new StringBuffer(error.getDefaultMessage());
            } else {
                sb.append(", ").append(error.getDefaultMessage());
            }
        }
        return BaseResultVO.error(400, sb.toString());
    }


    //405错误
    @ExceptionHandler({HttpRequestMethodNotSupportedException.class})
    public BaseResultVO request405(HttpRequestMethodNotSupportedException exception){
        log.error("405..HttpRequestMethodNotSupportedException", exception);
        return BaseResultVO.error(405, exception.getMessage());
    }
    //406错误
    @ExceptionHandler({HttpMediaTypeNotAcceptableException.class})
    public BaseResultVO request406(HttpMediaTypeNotAcceptableException exception){
        log.error("406..HttpRequestMethodNotSupportedException", exception);
        return BaseResultVO.error(406, exception.getMessage());
    }

    //自定义异常
    @ExceptionHandler(BaseException.class)
    public BaseResultVO baseExceptionHandler(BaseException exception) {
        log.error("501..BaseException", exception);
        return BaseResultVO.error(501, exception.getMessage());
    }
    //Mysql错误
    @ExceptionHandler({BadSqlGrammarException.class})
    public BaseResultVO badSqlGrammarExceptionHandler(BadSqlGrammarException exception){
        log.error("502..BadSqlGrammarException", exception);
        return BaseResultVO.error(502, exception.getMessage());
    }
    //503错误
    @ExceptionHandler({ConversionNotSupportedException.class, HttpMessageNotWritableException.class})
    public BaseResultVO server503(RuntimeException exception){
        log.error("503..ConversionNotSupportedException HttpMessageNotWritableException", exception);
        return BaseResultVO.error(503, exception.getMessage());
    }

    //运行时异常
    @ExceptionHandler(RuntimeException.class)
    public BaseResultVO runtimeExceptionHandler(RuntimeException exception) {
        log.error("1000..RuntimeException", exception);
        return BaseResultVO.error(1000, exception.getMessage());
    }

    // 其它异常
    @ExceptionHandler({Exception.class})
    public BaseResultVO otherException(Exception exception){
        log.error("500..Exception", exception);
        return BaseResultVO.error(500, exception.getMessage());
    }
}
